/******************************************************************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_legend_label.h"
#include "qwt_legend_data.h"
#include "qwt_graphic.h"
#include "qwt.h"

#include <qpainter.h>
#include <qdrawutil.h>
#include <qstyle.h>
#include <qevent.h>
#include <qstyleoption.h>

static const int cs_legendlabel_buttonFrame = 2;
static const int cs_legendlabel_margin      = 2;

static QSize buttonShift(const QwtLegendLabel* w)
{
    QStyleOption option;
    option.initFrom(w);

    const int ph = w->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option, w);
    const int pv = w->style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option, w);
    return QSize(ph, pv);
}

class QwtLegendLabel::PrivateData
{
public:
    PrivateData() : itemMode(QwtLegendData::ReadOnly), isDown(false), spacing(cs_legendlabel_margin)
    {
    }

    QwtLegendData::Mode itemMode;
    QwtLegendData legendData;
    bool isDown;

    QPixmap icon;

    int spacing;
};

/*!
   Set the attributes of the legend label

   \param legendData Attributes of the label
   \sa data()
 */
void QwtLegendLabel::setData(const QwtLegendData& legendData)
{
    m_data->legendData = legendData;

    const bool doUpdate = updatesEnabled();
    if (doUpdate)
        setUpdatesEnabled(false);

    setText(legendData.title());
    setIcon(legendData.icon().toPixmap());

    if (legendData.hasRole(QwtLegendData::ModeRole))
        setItemMode(legendData.mode());

    if (doUpdate)
        setUpdatesEnabled(true);
}

/*!
   \return Attributes of the label
   \sa setData(), QwtPlotItem::legendData()
 */
const QwtLegendData& QwtLegendLabel::data() const
{
    return m_data->legendData;
}

/*!
   \param parent Parent widget
 */
QwtLegendLabel::QwtLegendLabel(QWidget* parent) : QwtTextLabel(parent)
{
    m_data = new PrivateData;
    setMargin(cs_legendlabel_margin);
    setIndent(cs_legendlabel_margin);
}

//! Destructor
QwtLegendLabel::~QwtLegendLabel()
{
    delete m_data;
    m_data = NULL;
}

/*!
   Set the text to the legend item

   \param text Text label
    \sa QwtTextLabel::text()
 */
void QwtLegendLabel::setText(const QwtText& text)
{
    const int flags = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextExpandTabs | Qt::TextWordWrap;

    QwtText txt = text;
    txt.setRenderFlags(flags);

    QwtTextLabel::setText(txt);
}

/*!
   Set the item mode
   The default is QwtLegendData::ReadOnly

   \param mode Item mode
   \sa itemMode()
 */
void QwtLegendLabel::setItemMode(QwtLegendData::Mode mode)
{
    if (mode != m_data->itemMode) {
        m_data->itemMode = mode;
        m_data->isDown   = false;

        setFocusPolicy((mode != QwtLegendData::ReadOnly) ? Qt::TabFocus : Qt::NoFocus);
        setMargin(cs_legendlabel_buttonFrame + cs_legendlabel_margin);

        updateGeometry();
    }
}

/*!
   \return Item mode
   \sa setItemMode()
 */
QwtLegendData::Mode QwtLegendLabel::itemMode() const
{
    return m_data->itemMode;
}

/*!
   Assign the icon

   \param icon Pixmap representing a plot item

   \sa icon(), QwtPlotItem::legendIcon()
 */
void QwtLegendLabel::setIcon(const QPixmap& icon)
{
    m_data->icon = icon;

    int indent = margin() + m_data->spacing;
    if (icon.width() > 0)
        indent += icon.width() + m_data->spacing;

    setIndent(indent);
}

/*!
   \return Pixmap representing a plot item
   \sa setIcon()
 */
QPixmap QwtLegendLabel::icon() const
{
    return m_data->icon;
}

/*!
   \brief Change the spacing between icon and text

   \param spacing Spacing
   \sa spacing(), QwtTextLabel::margin()
 */
void QwtLegendLabel::setSpacing(int spacing)
{
    spacing = qMax(spacing, 0);
    if (spacing != m_data->spacing) {
        m_data->spacing = spacing;

        int indent = margin() + m_data->spacing;
        if (m_data->icon.width() > 0)
            indent += m_data->icon.width() + m_data->spacing;

        setIndent(indent);
    }
}

/*!
   \return Spacing between icon and text
   \sa setSpacing(), QwtTextLabel::margin()
 */
int QwtLegendLabel::spacing() const
{
    return m_data->spacing;
}

/*!
    Check/Uncheck a the item

    \param on check/uncheck
    \sa setItemMode()
 */
void QwtLegendLabel::setChecked(bool on)
{
    if (m_data->itemMode == QwtLegendData::Checkable) {
        const bool isBlocked = signalsBlocked();
        blockSignals(true);

        setDown(on);

        blockSignals(isBlocked);
    }
}

//! Return true, if the item is checked
bool QwtLegendLabel::isChecked() const
{
    return m_data->itemMode == QwtLegendData::Checkable && isDown();
}

//! Set the item being down
void QwtLegendLabel::setDown(bool down)
{
    if (down == m_data->isDown)
        return;

    m_data->isDown = down;
    update();

    if (m_data->itemMode == QwtLegendData::Clickable) {
        if (m_data->isDown)
            Q_EMIT pressed();
        else {
            Q_EMIT released();
            Q_EMIT clicked();
        }
    }

    if (m_data->itemMode == QwtLegendData::Checkable)
        Q_EMIT checked(m_data->isDown);
}

//! Return true, if the item is down
bool QwtLegendLabel::isDown() const
{
    return m_data->isDown;
}

//! Return a size hint
QSize QwtLegendLabel::sizeHint() const
{
    QSize sz = QwtTextLabel::sizeHint();
    sz.setHeight(qMax(sz.height(), m_data->icon.height() + 4));

    if (m_data->itemMode != QwtLegendData::ReadOnly) {
        sz += buttonShift(this);
        sz = qwtExpandedToGlobalStrut(sz);
    }

    return sz;
}

//! Paint event
void QwtLegendLabel::paintEvent(QPaintEvent* e)
{
    const QRect cr = contentsRect();

    QPainter painter(this);
    painter.setClipRegion(e->region());

    if (m_data->isDown) {
        qDrawWinButton(&painter, 0, 0, width(), height(), palette(), true);
    }

    painter.save();

    if (m_data->isDown) {
        const QSize shiftSize = buttonShift(this);
        painter.translate(shiftSize.width(), shiftSize.height());
    }

    painter.setClipRect(cr);

    drawContents(&painter);

    if (!m_data->icon.isNull()) {
        QRect iconRect = cr;
        iconRect.setX(iconRect.x() + margin());
        if (m_data->itemMode != QwtLegendData::ReadOnly)
            iconRect.setX(iconRect.x() + cs_legendlabel_buttonFrame);

        iconRect.setSize(m_data->icon.size());
        iconRect.moveCenter(QPoint(iconRect.center().x(), cr.center().y()));

        painter.drawPixmap(iconRect, m_data->icon);
    }

    painter.restore();
}

//! Handle mouse press events
void QwtLegendLabel::mousePressEvent(QMouseEvent* e)
{
    if (e->button() == Qt::LeftButton) {
        switch (m_data->itemMode) {
        case QwtLegendData::Clickable: {
            setDown(true);
            return;
        }
        case QwtLegendData::Checkable: {
            setDown(!isDown());
            return;
        }
        default:;
        }
    }
    QwtTextLabel::mousePressEvent(e);
}

//! Handle mouse release events
void QwtLegendLabel::mouseReleaseEvent(QMouseEvent* e)
{
    if (e->button() == Qt::LeftButton) {
        switch (m_data->itemMode) {
        case QwtLegendData::Clickable: {
            setDown(false);
            return;
        }
        case QwtLegendData::Checkable: {
            return;  // do nothing, but accept
        }
        default:;
        }
    }
    QwtTextLabel::mouseReleaseEvent(e);
}

//! Handle key press events
void QwtLegendLabel::keyPressEvent(QKeyEvent* e)
{
    if (e->key() == Qt::Key_Space) {
        switch (m_data->itemMode) {
        case QwtLegendData::Clickable: {
            if (!e->isAutoRepeat())
                setDown(true);
            return;
        }
        case QwtLegendData::Checkable: {
            if (!e->isAutoRepeat())
                setDown(!isDown());
            return;
        }
        default:;
        }
    }

    QwtTextLabel::keyPressEvent(e);
}

//! Handle key release events
void QwtLegendLabel::keyReleaseEvent(QKeyEvent* e)
{
    if (e->key() == Qt::Key_Space) {
        switch (m_data->itemMode) {
        case QwtLegendData::Clickable: {
            if (!e->isAutoRepeat())
                setDown(false);
            return;
        }
        case QwtLegendData::Checkable: {
            return;  // do nothing, but accept
        }
        default:;
        }
    }

    QwtTextLabel::keyReleaseEvent(e);
}
